package com.iqiyi.pps.epg.core.rpc.program;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.iqiyi.kiwi.utils.Configuration;
import com.iqiyi.kiwi.utils.JsonBinder;
import com.iqiyi.pps.epg.api.model.web.program.*;
import com.iqiyi.pps.epg.api.model.web.query.TFilter;
import com.iqiyi.pps.epg.api.model.web.query.TPage;
import com.iqiyi.pps.epg.api.model.web.query.TResponse;
import com.iqiyi.pps.epg.api.server.web.program.ProgramWebService;
import com.iqiyi.pps.epg.core.model.carousel.ProgramNode;
import com.iqiyi.pps.epg.core.model.carousel.ProgramNodeElement;
import com.iqiyi.pps.epg.core.model.carousel.ProgramQipuData;
import com.iqiyi.pps.epg.core.model.channel.ChannelBase;
import com.iqiyi.pps.epg.core.model.channel.ChannelBoss;
import com.iqiyi.pps.epg.core.model.log.InterfaceLog;
import com.iqiyi.pps.epg.core.model.program.*;
import com.iqiyi.pps.epg.core.model.rtmp.RtmpServer;
import com.iqiyi.pps.epg.core.model.stream.LiveChannelStream;
import com.iqiyi.pps.epg.core.rpc.qipu.QipuService;
import com.iqiyi.pps.epg.core.service.channel.ChannelService;
import com.iqiyi.pps.epg.core.service.log.InterfaceLogService;
import com.iqiyi.pps.epg.core.service.notifymail.NotifyMailService;
import com.iqiyi.pps.epg.core.service.program.IProgramAsyncService;
import com.iqiyi.pps.epg.core.service.program.ISnapAsyncService;
import com.iqiyi.pps.epg.core.service.program.ProgramService;
import com.iqiyi.pps.epg.core.service.push.AutoPushMsgService;
import com.iqiyi.pps.epg.core.service.rtmp.RtmpService;
import com.iqiyi.pps.epg.core.service.stream.LiveChannelStreamService;
import com.iqiyi.pps.epg.core.service.stream.LiveChannelStreamServiceImpl;
import com.iqiyi.pps.epg.core.service.ticket.ITicketService;
import com.iqiyi.pps.epg.core.utils.*;
import com.iqiyi.pps.epg.core.utils.mail.MailConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by karkarrotxu on 2014/12/4.
 */
public class ProgramWebServiceImpl implements ProgramWebService.Iface {
    public static final int MAX_LIMIT = 200;
    public static final String BIND_EPISODE_MSG = "关联直转点后节目ID已被其他节目绑定";
    public static final String MAX_EPISODE_START_SUMMAY_MSG = "直播前节目集锦不能超过" + MAX_LIMIT + "个";
    public static final String MAX_EPISODE_END_SUMMAY_MSG = "直播后节目集锦不能超过" + MAX_LIMIT + "个";
    public static final String MAX_EPISODE_SUMMAY_MSG = "关联直转点后节目ID不能超过1个";
    public static final String CHANNEL_NOTIFY_URL = Configuration.getString("channel.notify.url");
    public static final String CHANNEL_NOTIFY_TITLE = "《【${channel}】频道【${program}】节目--更新通知》";
    public static final String CHANNEL_NOTIFY_CONTENT = "节目名称：【${program}】节目，奇谱ID \"${pQipuId}\"</br>频道名称：【${channel}】频道，奇谱ID " +
            "\"${cQipuId}\"</br>节目时间：原${oldTime}</br>修改时间：改为${newTime}</br></br></br>节目发生变化，请及时更新节目单！</br></br></br>EPG直播中心---系统邮件";
    public static final int PROGRAM_MOVE_SUC = 0;
    public static final int PROGRAM_MOVE_ERR = 1;
    public static final int PROGRAM_MOVE_ERR_EXPIRED = 2;
    public static final int PROGRAM_MOVE_ERR_NOUP = 3;
    public static final int PROGRAM_MOVE_ERR_NODOWN = 4;
    public static final int PROGRAM_MOVE_ERR_OVERDAY = 5;
    public static final long PROGRAM_EDIT_RESERVE_TIME = Configuration.getLong("program.edit.forbidden.reserve.time") * 60 * 1000;
    public static final long PROGRAM_EDIT_FIX_TIME = 10 * 60 * 1000;
    public static final String NOT_ENOUGH_TIME = "请求插入的时间点：%s,实际插入的时间点：%s,预计结束的时间点：%s,插入节目总时间大于一天的剩余时间";
    public static final String INVALID_INSERT = "直播只能插入当前半小时之后的节目";
    public static final String STREAM_ERROR_TITLE = "轮播台【${channelName}】频道压流失败提醒";
    public static final String STREAM_ERROR_CONTENT = "节目名称：【${programName}】节目，奇谱ID \"${pQipuId}\"</br>频道名称：【${channelName}】频道，奇谱ID " +
            "\"${cQipuId}\"</br>节目时间：${startTime} ~ ${stopTime}</br>压流发生异常，请及时登录系统查看。</br></br></br>EPG直播中心---系统邮件";
    public static final int PROGRAM_INDEX_MOVE_SUC = 1;
    public static final int PROGRAM_INDEX_MOVE_ERR = -1;
    public static final int PROGRAM_INDEX_MOVE_ERR_NO_CURRENTTARGET = -2;
    public static final int PROGRAM_INDEX_MOVE_ERR_NO_AIMTARGET = -3;
    public static final int PROGRAM_INDEX_MOVE_ERR_OVERTIME_CURRENT = -4;
    public static final int PROGRAM_INDEX_MOVE_ERR_OVERTIME_AIM = -5;
    public static final int PROGRAM_INDEX_MOVE_ERR_NO_LIVE = -6;
    public static final int PROGRAM_INDEX_MOVE_ERR_START_END_TIME = -7;

    private static final String RTMP_URL_TEMPLATE = "rtmp://%s/live/%s";

    private static final String TEST_PROGRAM_TAG = "200003919_200978719";

    private static Logger logger = LoggerFactory.getLogger(ProgramWebServiceImpl.class);

    private static Object lockAddData = new Object();

    private ProgramService getProgramService() {
        return WriteSystemLogUtil.getInstance().getProgramService();
    }

    private IProgramAsyncService getProgramAsyncService() {
        return WriteSystemLogUtil.getInstance().getProgramAsyncService();
    }

    private ITicketService getTicketService() {
        return WriteSystemLogUtil.getInstance().getTicketService();
    }

    private ChannelService getChannelService() {
        return WriteSystemLogUtil.getInstance().getChannelService();
    }

    private ISnapAsyncService getSnapAsyncService() {
        return WriteSystemLogUtil.getInstance().getSnapAsyncService();
    }

    private QipuService getQipuService() {
        return WriteSystemLogUtil.getInstance().getQipuService();
    }

    private NotifyMailService getNoticeMailService() {
        return WriteSystemLogUtil.getInstance().getNoticeMailService();
    }

    public boolean queryAssignProgramList(long fatherId) {
        ChannelService channelService = getChannelService();
        ChannelBase channelBase = channelService.getChannelBase(fatherId);
        return TVMaoUtil.syncQuery(channelBase.getUniversalCode());
    }

    @Override
    public void forceSyncProgramList(long fatherId, long programId) {
        ProgramService service = getProgramService();
        if (programId > 0) {
            service.doSyncById(programId);
        } else {
            service.doSyncByFatherId(fatherId);
        }
    }

    @Override
    public boolean saveLogo(long id, String url) {
        ProgramService service = getProgramService();
        ProgramData entity = service.findProgramDataById(id);
        if (entity != null) {
            entity.setDefaultLogoUrl(url);
            service.editProgramData(entity);
            getProgramAsyncService().addVVNotify(entity);
            getProgramAsyncService().addLogoUrlCheck(entity);
            service.doSyncById(id);
            return true;
        }
        return false;
    }

    @Override
    public boolean saveSnapPicUrl(long id, String url) {
        ProgramService service = getProgramService();
        ProgramData entity = service.findProgramDataById(id);
        if (entity != null) {
            if (StringUtils.isEmpty(entity.getSnapPicUrl())) {
                service.updateSnapPicUrl(id, url);
                service.doSyncById(id);
            }
            writeProgramLog(id, Constants.LogType.MEIZI_SNAPSHOT_WRITE.getIndex(), url);
            return true;
        }
        return false;
    }

    @Override
    public String batchAdd(List<Long> list, String beginTime, long fatherId) {
        String ret = "success";
        try {
            if (list.size() == 0) {
                return ret;
            }
            ChannelService channelService = getChannelService();
            ChannelBase channelBase = channelService.getChannelBase(fatherId);
            if (Integer.valueOf(3).compareTo(channelBase.getLiveType()) != 0) {
                return "频道不是轮播台";
            }

            ProgramService service = getProgramService();
            List<ProgramData> pList = null;
            List<ProgramDataBase> pdbList = null;
            List<Long> idList = new ArrayList<Long>();
            long currentAddTime = System.currentTimeMillis();
            long checkQupuId = list.get(0);
            int rest = (int) (checkQupuId - checkQupuId / 100 * 100);
            List<Long> illegalList = new ArrayList<Long>();
            if (rest == 0) {
                List<ProgramQipuData> qipuDatas = CarouselAssistUtil.queryForData(list, channelBase, null, 0);

                pList = new ArrayList<ProgramData>();
                long startInsertTime = currentAddTime + PROGRAM_EDIT_RESERVE_TIME + PROGRAM_EDIT_FIX_TIME;
                long startTime = DateTimeUtil.parseLongFormat(beginTime);
                if (startTime < startInsertTime) {
                    startTime = startInsertTime;
                }
                long checkYesterdayEndTime = service.findYesDayEndTime(fatherId, startTime);
                if (startTime < checkYesterdayEndTime) {
                    startTime = checkYesterdayEndTime;
                }
                long needTime = 0L;
                for (ProgramQipuData temp : qipuDatas) {
                    needTime += 1000L * temp.getDuration();
                }
                String beginTimeShortMode = DateTimeUtil.transShortFormat(startTime);
                String expectEndTime = DateTimeUtil.transShortFormat(startTime + needTime);
                if (qipuDatas.size() > 1 && expectEndTime.compareTo(beginTimeShortMode) > 0) {
                    ret = String.format(NOT_ENOUGH_TIME, beginTime, beginTimeShortMode, expectEndTime);
                    logger.info("need time over day " + ret + "[fatherId={}]", fatherId);
                    return ret;
                }
                ProgramData original = null;
                ApiLegoUtil.fillAlbumRelation(qipuDatas);
                for (ProgramQipuData temp : qipuDatas) {
                    original = temp.getOriginal();
                    original.setStartPlayTime(new Timestamp(startTime));
                    original.setStreamStartTime(new Timestamp(startTime));
                    startTime += temp.getDuration() * 1000;
                    original.setStopPlayTime(new Timestamp(startTime));
                    original.setStreamEndTime(new Timestamp(startTime));
                    ProgramData.calPlayStatus(original);
                    if (!temp.isIllegal()) {
                        pList.add(original);
                    } else {
                        if (original.getCarouselEpisode() != null && original.getCarouselEpisode().longValue() > 0) {
                            illegalList.add(original.getCarouselEpisode());
                        }
                    }
                }

            } else if (rest == 23) {
                pList = service.findByQipuIds(list);
                long checkTime = currentAddTime + PROGRAM_EDIT_RESERVE_TIME;
                for (ProgramData temp : pList) {
                    if (temp.getStartPlayTime().getTime() < checkTime) {
                        ret = INVALID_INSERT;
                        return ret;
                    }
                    temp.setFatherId((int) fatherId);
                    temp.setCarouselEpisode(temp.getQipuId());
                    temp.setQipuId(0);
                    temp.setId(0);
                    temp.setSync(0);
                    temp.setLive(ProgramData.TYPE_LIVE);
                    temp.setType(7);//轮播台节目
                    ProgramData.calPlayStatus(temp);
                    idList.add(temp.getId());
                }
            } else {
                logger.warn("no such rest qipuId " + rest);
                return "fail";
            }
            logger.info("[batchAdd][saveProgramDataList");
            if (illegalList.size() > 0) {
                Map<String, String> map = new HashMap<String, String>();
                map.put(MailConstant.C_ID, "" + channelBase.getId());
                map.put(MailConstant.C_NAME, channelBase.getName());
                map.put(MailConstant.C_QIPU_ID, "" + channelBase.getQipuId());
                map.put(MailConstant.P_QIPU_IDS, illegalList.toString().replaceAll("\\[|\\]", ""));
                NotifyMailService notifyMailService = (NotifyMailService) ApplicationContextUtil.getBean(NotifyMailService.class);
                notifyMailService.addMailAsyncTask(MailConstant.TOS_TYPE_FROM_LOG, MailContentUtil.ContentType.LB_ADD_PROGRAM_ERROR.getTypeIndex(), map);

            }
            service.saveProgramDataList(pList, channelBase.getId());
            channelService.notifyHasPrograms(fatherId);
            if (idList.size() > 0) {
                pdbList = service.findDataBaseByProgramDataIds(idList);
                if (pdbList != null) {
                    for (ProgramDataBase pdb : pdbList) {
                        pdb.setId(0);
                    }
                    logger.info("[batchAdd][insertProgramDataBaseList]");
                    service.insertProgramDataBaseList(pdbList);
                }
            }

            if (null != pList.get(0)) {
                checkProgramModification(channelBase.getId(), pList.get(0).getId(), channelBase.getLiveType());
            }

        } catch (Exception e) {
            logger.error("[batchAdd][fatherId=" + fatherId + "][exception:{}]", e);
            ret = "fail";
        }
        return ret;
    }

    private JSONObject getRetObj(long retValue) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("retValue", retValue);
        return jsonObject;
    }


    @Override
    public TResponse addProgram(TProgram entity) throws TException {
        TResponse tResponse = new TResponse();
        tResponse.setCode(Constants.CODE_ERROR);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("retValue", 0);
        if (entity.getId() > 0) {
            jsonObject.put("retValue", -1);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }
        ChannelService channelService = getChannelService();
        ChannelBase channelBase = channelService.getChannelBase(entity.getFatherId());
        if (channelBase == null || (channelBase.getIsEnable() != null && channelBase.getIsEnable().intValue() == -1)) {
            jsonObject.put("retValue", -2);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }
        long regId = 0;
        try {
            synchronized (lockAddData) {
                ProgramService service = getProgramService();
                int delayTime = 0;
                boolean lsType = channelBase.getLiveType() == ChannelBase.LIVE_TYPE_LS;
                boolean lbType = channelBase.getLiveType() == ChannelBase.LIVE_TYPE_LB;
                if (lsType) {
                    delayTime = channelBase.getSliceDelay();
                }

                boolean flag = isInRange((int) entity.getFatherId(), entity.getStartPlayTime(), entity.getEndPlayTime(), -1);
                if (flag) {
                    jsonObject.put("retValue", -10001);
                    tResponse.setJsonData(jsonObject.toJSONString());
                    return tResponse;
                }
                ProgramData programData = new ProgramData();
                //relate oa-doc
                programData.setNeedOA(entity.getNeedOA());
                programData.setOaDocNo(entity.getOaDocNo());
                programData.setOaDocUrl(entity.getOaDocUrl());
                programData.setOaDocEditorStatus(entity.getOaDocEditorStatus());
                //relate oa-doc

                QipuService qipuService = (QipuService) ApplicationContextUtil.getBean(QipuService.class);
                List<Long> qipuIdList = qipuService.registerQipuId(23, 1);
                programData.setQipuId(qipuIdList.get(0));
                programData.setFatherId((int) entity.getFatherId());
                programData.setPname(entity.getPname());
                Timestamp saveStartTime = Timestamp.valueOf(entity.getStartPlayTime());
                Timestamp saveEndTime = Timestamp.valueOf(entity.getEndPlayTime());
                if (delayTime > 0) {
                    saveStartTime.setTime(saveStartTime.getTime() + DateTimeUtil.SECOND * delayTime);
                    saveEndTime.setTime(saveEndTime.getTime() + DateTimeUtil.SECOND * delayTime);
                    entity.setStreamStartPlayTime(DateTimeUtil.transLongFormat(Timestamp.valueOf(entity.getStreamStartPlayTime()).getTime() + DateTimeUtil.SECOND * delayTime));
                    entity.setStreamEndPlayTime(DateTimeUtil.transLongFormat(Timestamp.valueOf(entity.getStreamEndPlayTime()).getTime() + DateTimeUtil.SECOND * delayTime));
                }
                programData.setStartPlayTime(saveStartTime);
                programData.setStopPlayTime(saveEndTime);
                programData.setAddTime(new Timestamp(System.currentTimeMillis()));
                programData.setBossStatus(ProgramData.FREE);
                programData.setMemberFree(1);
                programData.setMemberOnly(0);
                programData.setFreeStatus(1);
                programData.setLive(0);


                if (entity.getBarCode() != null) {
                    if (lsType) {
                        programData.setBarCode(entity.getBarCode() == null ? "" : entity.getBarCode());
                    }
                }
                programData.setSubscribe(entity.getSubscribe());
                programData.setMaxPlaybackPeriod(channelBase.getMaxPlaybackPeriod());
                programData.setNoticeStartTime(new Timestamp(saveStartTime.getTime()));
                programData.setNoticeStopTime(new Timestamp(saveEndTime.getTime()));
                if (!lsType) {
                    entity.setMatchSummary(null);
                }
                if (lbType) {
                    entity.setFreeStatus(true);
                }
                putCommonValue(entity, programData);
                if (lsType) {
                    if (programData.getTest() == 1) {
                        programData.setProgramTag(TEST_PROGRAM_TAG);
                    } else {
                        programData.setProgramTag(entity.getProgramTag());
                    }
                }
                int bindRetValue = dealMatchSummary(entity, programData);
                jsonObject.put("sportBind", bindRetValue);

                programData.setSnapShotType(entity.getSnapShotType());
                if (programData.getSnapShotType() == 1) {
                    programData.setSnapShotGap(entity.getSnapShotGap());
                } else {
                    programData.setSnapShotGap(-1);
                }
                // PPC常规直播数热门据投递

                if (lsType) {
                    ApiPpcUtil.postPpcHotSync(programData.getQipuId(), programData.getChatRoomId(), programData.getStartPlayTime().getTime(),
                            programData.getStopPlayTime().getTime(), programData.getRecommendRate(), programData.getHot(), programData.getPname(),
                            programData.getTest(), 0);
                }

                regId = service.saveProgramData(programData);
                if (regId > 0) {
                    getProgramAsyncService().addVVNotify(programData);
                    getProgramAsyncService().addTicketSysNotify(programData, channelBase.getQipuId(), entity.getOpUser());
                    if (lsType && programData.getTest() == 0) {
                        String episodeGrade = channelService.getConfigData("EpisodeGradeType", programData.getEpisodeGrade()).getDescr();
                        doSendCreateLiveNotify(programData, channelBase, episodeGrade, entity.getOpUser());
                    }
                    if (lsType && channelBase.getHasStream() == ChannelBase.HAS_STREAM) {
                        IProgramAsyncService programAsyncService = (IProgramAsyncService) ApplicationContextUtil.getBean(IProgramAsyncService.class);
                        programAsyncService.addBroadCoastToQipu(programData, true);
                    }
                    channelService.notifyHasPrograms(programData.getFatherId());
                }
                entity.setId(regId);
                service.editProgramDataBaseList(entity);
                service.doSyncById(regId);

                if (programData.getFreeStatus() == 0) {
                    doChargeChannel(programData);
                }

                checkProgramModification(programData.getFatherId(), programData.getId(), channelBase.getLiveType());
                if (programData.getSnapShotType() == 1 && lsType) {
                    if (regId > 0) {
                        getSnapAsyncService().addProgramTask(programData);
                    }
                }
            }
            tResponse.setCode(Constants.CODE_SUC);
            jsonObject.put("retValue", regId);
        } catch (Exception e) {
            logger.error("ERROR", e);
        }
        tResponse.setJsonData(jsonObject.toJSONString());
        return tResponse;
    }

    public String accoutPassportSign(List<ProgramDataBase> dataBaseList) {
        String uid = null;
        String nickName = null;
        for (ProgramDataBase programDataBase : dataBaseList) {
            if (programDataBase.getType() == 301) {
                uid = programDataBase.getValue();
            } else if (programDataBase.getType() == 302) {
                nickName = programDataBase.getValue();
            }
        }
        if (StringUtils.isBlank(uid) || StringUtils.isBlank(nickName)) {
            return null;
        }
        return uid + "|" + nickName;
    }

    public String accoutPassportSign2(List<TProgramBase> dataBaseList) {
        String uid = null;
        String nickName = null;
        if (dataBaseList != null) {
            for (TProgramBase programDataBase : dataBaseList) {
                if (programDataBase.getType() == 301) {
                    uid = programDataBase.getValue();
                } else if (programDataBase.getType() == 302) {
                    nickName = programDataBase.getValue();
                }
            }
        }

        if (StringUtils.isBlank(uid) || StringUtils.isBlank(nickName)) {
            return null;
        }
        return uid + "|" + nickName;
    }

    @Override
    public TResponse editProgram(TProgram entity) throws TException {
        TResponse tResponse = new TResponse();
        tResponse.setCode(Constants.CODE_ERROR);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("retValue", 0);
        boolean needSendPpcHotSync = false;
        long time1 = System.currentTimeMillis();
        if (entity.getId() == 0) {
            jsonObject.put("retValue", 1);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }
        ProgramService service = getProgramService();
        ProgramData programData = service.findProgramDataById(entity.getId());

        needSendPpcHotSync = checkNeedPpcHotSync(programData, entity);

        List<ProgramDataBase> dataBaseList = service.findDataBaseByProgramDataId(programData.getId());

        SnapChangeAssist snapChangeAssist = new SnapChangeAssist(programData);
        VVChangeAssist vvChangeAssist = new VVChangeAssist(programData, accoutPassportSign(dataBaseList));
        TicketChangeAssist ticketChangeAssist = new TicketChangeAssist(programData);
        DirectorChangeAssist directorChangeAssist = new DirectorChangeAssist(programData);
        if (entity.getUpdateTime() == null || DateTimeUtil.transLongFormat(programData.getUpdateTime().getTime()).compareTo(entity.getUpdateTime()) > 0) {
            logger.error("entity.getUpdateTime()={} ", entity.getUpdateTime());
            logger.error("programData.getUpdateTime()={} ", DateTimeUtil.transLongFormat(programData.getUpdateTime().getTime()));
            jsonObject.put("retValue", 3);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }

        ChannelService channelService = getChannelService();
        ChannelBase editChannelBase = channelService.getChannelBase(programData.getFatherId());
        // 提前半小时轮播台节目禁止修改判断
        long gapTimeOrigin = programData.getStartPlayTime().getTime() - System.currentTimeMillis();
        long gapTimeModify = DateTimeUtil.parseLongFormat(entity.getStartPlayTime()) - System.currentTimeMillis();
        boolean lbType = editChannelBase.getLiveType() == ChannelBase.LIVE_TYPE_LB;
        boolean lsType = ChannelBase.LIVE_TYPE_LS == editChannelBase.getLiveType().intValue();
        if (lbType &&
                (gapTimeOrigin < PROGRAM_EDIT_RESERVE_TIME || gapTimeModify < PROGRAM_EDIT_RESERVE_TIME)) {
            jsonObject.put("retValue", 2);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }

        String oldTime = DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()) + " - " +
                DateTimeUtil.transLongFormat(programData.getStopPlayTime().getTime());
        String newTime = entity.getStartPlayTime() + " - " + entity.getEndPlayTime();
        //  long oldStartPlayTime = programData.getStartPlayTime().getTime();

        boolean modifyTime = false;
        boolean modifyCheckType = entity.getCheckType() != programData.getCheckType();

        boolean isSame = checkWithNotice(programData);
        logger.info("[ same time : start_play_time,notice_start_time][qipuId={}]", programData.getQipuId());
        if (entity.getStartPlayTime() != null) {
            Timestamp newStartPlayTime = Timestamp.valueOf(entity.getStartPlayTime());
            if (newStartPlayTime.getTime() != programData.getStartPlayTime().getTime()) {
                modifyTime = true;
                programData.setStartPlayTime(newStartPlayTime);
                programData.setDelayTimes(0);
            }
            if (isSame) {
                programData.setNoticeStartTime(Timestamp.valueOf(entity.getStartPlayTime()));
                AutoPushMsgService autoPushMsgService = (AutoPushMsgService) ApplicationContextUtil.getBean(AutoPushMsgService.class);
                autoPushMsgService.updatePushByEpisodeId(programData);
            }
        }
        if (entity.getEndPlayTime() != null) {
            Timestamp newEndPlayTime = Timestamp.valueOf(entity.getEndPlayTime());
            if (newEndPlayTime.getTime() != programData.getStopPlayTime().getTime()) {
                modifyTime = true;
                programData.setStopPlayTime(newEndPlayTime);
            }
            if (isSame) {
                programData.setNoticeStopTime(Timestamp.valueOf(entity.getEndPlayTime()));
            }
        }
        if (editChannelBase.getLiveType() != null) {

            if (lsType || lbType) {
                programData.setPname(entity.getPname());
            }
            if (lsType) {
                programData.setBarCode(entity.getBarCode() == null ? "" : entity.getBarCode());
            }
        }

        // 判断道具启用是否被修改 (聊天室启用的前提下)
        if (entity.getChatEnable() == 1 && programData.getDaojuEnable() == 0 && entity.getDaojuEnable() == 1
                && StringUtils.isNotBlank(programData.getDaojuId())) {
            doSendDaojuRemind(programData, MailContentUtil.DAOJU_ENABLED_REMIND_TITLE);
        } else if (programData.getDaojuEnable() == 1 && entity.getDaojuEnable() == 0) {
            doSendDaojuRemind(programData, MailContentUtil.DAOJU_DISABLED_REMIND_TITLE);
        }
        if (!lsType) {
            entity.setMatchSummary(null);
        }
        if (lbType) {
            entity.setFreeStatus(true);
        }
        putCommonValue(entity, programData);
        if (lsType) {
            if (programData.getTest() == 1) {
                programData.setProgramTag(TEST_PROGRAM_TAG);
            } else {
                programData.setProgramTag(entity.getProgramTag());
            }
        }
        int bindRetValue = dealMatchSummary(entity, programData);
        jsonObject.put("sportBind", bindRetValue);

        int originalSnapShotType = programData.getSnapShotType();
        if (1 == originalSnapShotType && entity.getSnapShotType() == 0) {
            jsonObject.put("retValue", 4);
            tResponse.setJsonData(jsonObject.toJSONString());
            return tResponse;
        }
        programData.setSnapShotType(entity.getSnapShotType());
        if (programData.getSnapShotType() == 1) {
            programData.setSnapShotGap(entity.getSnapShotGap());
        } else {
            programData.setSnapShotGap(-1);
        }
        // PPC常规直播数热门据投递
        if (lsType && needSendPpcHotSync) {
            ApiPpcUtil.postPpcHotSync(programData.getQipuId(), programData.getChatRoomId(), programData.getStartPlayTime().getTime(),
                    programData.getStopPlayTime().getTime(), programData.getRecommendRate(), programData.getHot(), programData.getPname(),
                    programData.getTest(), 0);
        }

        if (programData.getFreeStatus() != 1 && modifyTime) {
            programData.setPaidStartTime(new Timestamp(programData.getStartPlayTime().getTime()));
            programData.setPaidEndTime(new Timestamp(programData.getStopPlayTime().getTime()));
        }
        // 更新聊天室开始和结束时间
        if (modifyTime || modifyCheckType) {
            ApiChatUtil.updateChat(entity.getUid(), programData.getChatRoomId() + "", programData.getStreamStartTime().getTime() / 1000,
                    programData.getStreamEndTime().getTime() / 1000, programData.getCheckType());
        }
        service.editProgramData(programData);
        service.editProgramDataBaseList(entity);
        service.doSyncById(programData.getId());
        if (ProgramData.PAIED_AVAILABLE.equals(programData.getBossStatus()) && modifyTime) {
            doChargeChannel(programData);
        }

        logger.info("[ProgramWebServiceImpl][editProgram][success][id = {}][modifyTime = {}]",
                programData.getId(), modifyTime ? "True" : "False");

        // 轮播台中引用的节目单发生变化时通知
        if (true == modifyTime && lsType) {
            sendEmailNotify(oldTime, newTime, programData, editChannelBase);
        }
        checkProgramModification(programData.getFatherId(), programData.getId(), editChannelBase.getLiveType());
        if (lsType) {
            vvChangeAssist.checkAgain(programData, accoutPassportSign2(entity.getRelationList()));
            snapChangeAssist.checkAgain(programData);
            directorChangeAssist.checkAgain(programData);
            ticketChangeAssist.checkAgain(programData);
            if (snapChangeAssist.isChange()) {
                getSnapAsyncService().addProgramTask(programData);
            }
            if (vvChangeAssist.isChange()) {
                getProgramAsyncService().addVVNotify(programData);
            }
            if (programData.getDirectorEnable() == 1 && directorChangeAssist.isChange()) {
                getProgramAsyncService().addDirectorNotify(programData);
            }
            if (ticketChangeAssist.isChange()) {
                getProgramAsyncService().addTicketSysNotify(programData, editChannelBase.getQipuId(), entity.getOpUser());
            }
        }

        logger.info("cost time [{}]", System.currentTimeMillis() - time1);
        tResponse.setCode(Constants.CODE_SUC);
        tResponse.setJsonData(jsonObject.toJSONString());
        return tResponse;
    }

    private boolean checkWithNotice(ProgramData programData) {
        String notice1 = getTimeValue(programData.getStartPlayTime()) + "|" + getTimeValue(programData.getStopPlayTime());
        String notice2 = getTimeValue(programData.getNoticeStartTime()) + "|" + getTimeValue(programData.getNoticeStopTime());
        return notice1.equals(notice2);
    }

    private long getTimeValue(Timestamp timestamp) {
        return timestamp == null ? 0 : timestamp.getTime();
    }

    private int dealMatchSummary(TProgram entity, ProgramData programData) {
        int retValue = 0;
        boolean needRemove = false;
        boolean needAdd = false;
        if (programData.getMatchSummary() == null) {
            if (entity.getMatchSummary() == null) {
                return retValue;
            } else {
                needAdd = true;
            }
        } else if (programData.getMatchSummary().equals(entity.getMatchSummary())) {
            return retValue;
        } else {
            needRemove = true;
            if (entity.getMatchSummary() != null) {
                needAdd = true;
            }
        }

        JSONObject jsonObject = null;
        Map<String, Object> params = new HashMap<>();
        params.put("programQipuId", programData.getQipuId());
        params.put("programName", programData.getPname());
        if (needRemove) {
            jsonObject = JSONObject.parseObject(programData.getMatchSummary());
            boolean result = ApiLegoUtil.updateSportRelation(ApiLegoUtil.SPORT_REMOVE_RELATION, jsonObject.getLongValue("id"), programData.getQipuId(), programData.getPname());
            params.put("matchId", jsonObject.getLongValue("id"));
            writeProgramLog(programData.getId(), Constants.LogType.PROGRAM_UNBIND_SPORT.getIndex(), entity.getOpUser(), result + "|" + params.toString());
            if (result) {
                programData.setMatchSummary(null);
            } else {
                retValue += -1;
            }
        }

        if (needAdd) {
            jsonObject = JSONObject.parseObject(entity.getMatchSummary());
            boolean result = ApiLegoUtil.updateSportRelation(ApiLegoUtil.SPORT_ADD_RELATION, jsonObject.getLongValue("id"), programData.getQipuId(), programData.getPname());
            params.put("matchId", jsonObject.getLongValue("id"));
            writeChannelLog(programData.getFatherId(), Constants.LogType.PROGRAM_BIND_SPORT.getIndex(), entity.getOpUser(), result + "|" + params.toString());
            if (result) {
                programData.setMatchSummary(entity.getMatchSummary());
            } else {
                retValue += -10;
            }
        }
        return retValue;
    }

    private void putCommonValue(TProgram entity, ProgramData programData) {
        if (entity.getChatEnable() == 0) {
            entity.setChatDisplay(0);
        }

        programData.setType(entity.getType());
        programData.setChatPopups(entity.getChatPopups());
//        programData.setAllowPopups(entity.isAllowPopups() ? 1 : 0);
        programData.setAllowPopups(entity.getChatPopups());
        programData.setAllowComment(entity.isAllowComment() ? 1 : 0);
        programData.setStreamStartTime(Timestamp.valueOf(entity.getStreamStartPlayTime()));
        programData.setStreamEndTime(Timestamp.valueOf(entity.getStreamEndPlayTime()));
        programData.setQiyiProduct(entity.isQiyiProduct() ? 1 : 0);
        programData.setQiyiExclusive(entity.isQiyiExclusive() ? 1 : 0);
        programData.setResourceId(entity.getResourceId());
        programData.setChatFake(entity.getChatFake());
        programData.setVipType(entity.getVipType() >= 0 && entity.getVipType() < 3 ? entity.getVipType() : 0);

        if (entity.getPublicLevel() > -1) {
            programData.setPublicLevel(entity.getPublicLevel());
        }
        if (programData.getDirectorEnable() == 0 && entity.getDirectorEnable() == 1) {
            programData.setDirectorEnable(1);
        }
        boolean isFreeStatus = entity.isFreeStatus();

        if ((isFreeStatus != (programData.getFreeStatus() == 1))) {
            if (isFreeStatus) {
                programData.setFreeStatus(1);
                programData.setBossStatus(ProgramData.FREE);
                programData.setMemberFree(1);
                programData.setMemberOnly(0);
                programData.setPaidEndTime(null);
                programData.setPaidStartTime(null);
                programData.setChargeStatus(ProgramData.CHARGE_STATUS_FREE);
            } else {
                programData.setFreeStatus(0);
                programData.setBossStatus(ProgramData.PAIED_NOT_AVAILABLE);
                programData.setChargeStatus(ProgramData.CHARGE_STATUS_FREE);
                programData.setMemberFree(1);
                programData.setMemberOnly(0);
                long startTime = entity.getPaidStartTime() == null ? programData.getStartPlayTime().getTime() : DateTimeUtil.parseLongFormat(entity.getPaidStartTime());
                long endTime = entity.getPaidEndTime() == null ? programData.getStopPlayTime().getTime() : DateTimeUtil.parseLongFormat(entity.getPaidEndTime());
                programData.setPaidStartTime(new Timestamp(startTime));
                programData.setPaidEndTime(new Timestamp(endTime));
                boolean flag = ApiBossUtil.channelCharge(programData.getId(), programData.getQipuId(), programData.getPname(), startTime, endTime, programData.getVipType());
                logger.info("[putCommonValue][flag:{}]", flag);

                try {
                    ChannelService channelService = getChannelService();
                    ChannelBase channelBase = channelService.getChannelBase(programData.getFatherId());
                    boolean ChannelFlag = ApiBossUtil.channelCharge(channelBase.getId(), channelBase.getQipuId(), channelBase.getName(), startTime, endTime, programData.getVipType());
                    logger.info("[putCommonValue][ChannelService:{}]", ChannelFlag);
                } catch (Exception e) {
                    logger.info("[putCommonValue][ChannelService:{}]", e);
                }
            }
        }
        programData.setImageSummaryId(entity.getImgSummaryId());
        programData.setDescription(entity.getDescription());
        programData.setAudioChannel(entity.getAudioChannel());
        programData.setLeftAudioChannel(entity.getLeftChannel());
        programData.setRightAudioChannel(entity.getRightChannel());
        programData.setQitanId(entity.getQitanId());
        programData.setVideoLength(entity.getVideoPieceLength());
        programData.setWaterMarkFlag(entity.isWaterMarkFlag() ? 1 : 0);
        programData.setLogoHidden(entity.getLogoHidden());
        programData.setWeiboTopic(entity.getWeiboTopic());
        programData.setTag(entity.getTag());
        programData.setOrderBy(entity.getOrderBy());
        programData.setEpisodeGrade(entity.getEpisodeGrade());
        programData.setSubscribe(entity.getSubscribe());
        programData.setCategory(entity.getCategory());

  /* 2016/08/31 project_type*/
        if (entity.getProjectType() != null) {
            programData.setProjectType(entity.getProjectType());
        }

        programData.setCheckType(entity.getCheckType() != 2 ? 1 : 2);

         /* 2016/05/20 new add start*/
        programData.setSubjectUrl(entity.getSubjectUrl());
        programData.setRecommendRate(entity.getRecommendRate());
        programData.setRecommendRemark(entity.getRecommendRemark());
        programData.setHot(entity.getHot());
        programData.setTest(entity.getTest());
        programData.setChatRights(entity.getChatRights());

        programData.setTabConrtols(entity.getTabControls());

        ProgramData.calPlayStatus(programData);
         /* 2016/05/20 new add end*/
        if (programData.getChatRoomId() > 0) {
            if (programData.getChatEnable() == 1 && entity.getChatEnable() == 0) {
                long flag = ApiChatUtil.deleteChat(programData.getChatRoomId(), entity.getUid());
                writeChannelLog(programData.getFatherId(), Constants.LogType.CHAT_ROOM_DEL.getIndex(), entity.getOpUser(), "pid:" + programData.getId() + ":roomId:" + programData.getChatRoomId() + "; flag:" + flag);
                if (flag > -1) {
                    programData.setChatEnable(0);
                }
            } else if (programData.getChatEnable() == 0 && entity.getChatEnable() == 1) {
                int flag = ApiChatUtil.openChat(programData.getChatRoomId(), entity.getUid());
                writeChannelLog(programData.getFatherId(), Constants.LogType.CHAT_ROOM_OPEN.getIndex(), entity.getOpUser(), "pid:" + programData.getId() + ":roomId:" + programData.getChatRoomId() + "; flag:" + flag);
                if (flag > -1) {
                    programData.setChatEnable(1);
                }
            }
        } else {
            programData.setChatEnable(entity.getChatEnable());
            if (entity.getChatEnable() == 1) {
                long chatRoomId = ApiChatUtil.createChat(entity.getUid(), programData.getQipuId(), entity.getPname(), programData.getStreamStartTime().getTime() / 1000, programData.getStreamEndTime().getTime() / 1000,
                        programData.getCheckType());
                if (chatRoomId > 0) {
                    programData.setChatRoomId(chatRoomId);
                }
                writeChannelLog(programData.getFatherId(), Constants.LogType.CHAT_ROOM_CREATE.getIndex(), entity.getOpUser(), "pid:" + programData.getId() + ":roomId:" + chatRoomId);
            }
        }
        programData.setChatDisplay(entity.getChatDisplay());
        /*2018.01.12 add displayRecommend*/
        programData.setDisplayRecommend(entity.getDisplayRecommend());
        //20180402 add dbtRegion
        programData.setDbtRegion(entity.getDbtRegion());

        Boolean isDaojuEnabled = programData.getDaojuEnable() == 0 && entity.getDaojuEnable() == 1;
        Boolean isDaojuDisabled = programData.getDaojuEnable() == 0 && entity.getDaojuEnable() == 0;
        programData.setDaojuEnable(entity.getDaojuEnable());

        if (entity.getChatEnable() == 1 && entity.getDaojuEnable() == 1) {
            String daojuStar = entity.getDaojuStar();
            JSONObject daojuStarJson = JSON.parseObject(daojuStar);
            String isGroup = daojuStarJson.getString("daojuStarFlag");
            JSONArray starArray = daojuStarJson.getJSONArray("starList");
            // 如果节目道具关闭后开启，需要开启渠道
            if (isDaojuEnabled && StringUtils.isNotBlank(programData.getDaojuId())) {
                ApiDaojuUtil.linkDaoju(programData.getQipuId(), entity.getUserName(), programData.getDaojuId(),
                        DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                        DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                        programData.getChatRoomId() + "",
                        entity.isFreeStatus() ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                        ApiDaojuUtil.DAOJU_LINK_STATUS_ON, null);
            }

            String daojuStarLocal = programData.getDaojuStar();
            if (StringUtils.isNotBlank(daojuStarLocal)) {
                String isGroupLocal = JSON.parseObject(daojuStarLocal).getString("daojuStarFlag");
                if (isGroup != isGroupLocal) {
                    ApiDaojuUtil.linkDaoju(programData.getQipuId(), entity.getUserName(), programData.getDaojuId(),
                            DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                            DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                            programData.getChatRoomId() + "",
                            entity.isFreeStatus() ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                            ApiDaojuUtil.DAOJU_LINK_STATUS_ON, isGroup);
                }
            }
            if (StringUtils.isNotBlank(programData.getDaojuStar()) && !programData.getDaojuStar().equals(daojuStar)) {
                // 更新时，如果没有包含id，则需要加上id=-1
                for (int i = 0; i < starArray.size(); i++) {
                    JSONObject object = starArray.getJSONObject(i);
                    if (!object.containsKey("id")) {
                        object.put("id", -1);
                    }
                }
                daojuStarJson.remove("starList");
                daojuStarJson.put("starList", starArray);
                daojuStar = daojuStarJson.toJSONString();
                String response = ApiDaojuUtil.updateStarList(programData.getDaojuId(), starArray.toJSONString());
                // 将更新后的数据入库
                JSONObject jsonResponse = JSONObject.parseObject(response);
                JSONArray startList = jsonResponse.getJSONObject("data").getJSONArray("star_list");
                daojuStarJson.remove("starList");
                daojuStarJson.put("starList", startList);
                daojuStar = daojuStarJson.toJSONString();
                programData.setDaojuStar(daojuStar);
            }

            if (StringUtils.isBlank(entity.getDaojuId())) {
                JSONObject jsonData = ApiDaojuUtil.addDaoju(programData.getQipuId(), entity.getUserName(), programData.getPname(), programData.getDescription(),
                        DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                        DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                        programData.getChatRoomId() + "",
                        entity.isFreeStatus() ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                        isGroup, starArray.toJSONString());
                String daojuId = "";
                if (jsonData != null) { //添加成功后，获取id入库
                    daojuId = jsonData.getString("partner_code");
                    JSONArray jsonArray = jsonData.getJSONArray("star_list");
                    daojuStarJson.remove("starList");
                    daojuStarJson.put("starList", jsonArray);
                    programData.setDaojuStar(daojuStarJson.toJSONString());
                }

                if (!"".equals(daojuId)) {
                    doSendDaojuRemind(programData, MailContentUtil.DAOJU_NEED_REMIND_TITLE);
                }
                programData.setDaojuId(daojuId);
                programData.setDaojuName(programData.getPname());
                writeChannelLog(programData.getFatherId(), Constants.LogType.DAOJU_ADD.getIndex(), entity.getOpUser(), "pid:" +
                        programData.getId() + ":daojuId:" + daojuId + "; flag:" + (!"".equals(daojuId) ? "操作成功" : "操作失败"));
            }

        } else if (StringUtils.isNotBlank(entity.getDaojuId()) && !isDaojuDisabled) {
            String status = entity.getChatEnable() == 1 && entity.getDaojuEnable() == 1 ? "1" : "2";
            programData.setDaojuId(entity.getDaojuId());
            programData.setDaojuName(entity.getDaojuName());
            int flag = ApiDaojuUtil.linkDaoju(programData.getQipuId(), entity.getUserName(), programData.getDaojuId(),
                    DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                    DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                    programData.getChatRoomId() + "",
                    entity.isFreeStatus() ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                    status, null);
            if (flag == 0) {
                if (programData.getDaojuEnable() == 1) {
                    doSendDaojuRemind(programData, programData.getId() == 0 ? MailContentUtil.DAOJU_NEED_REMIND_TITLE : MailContentUtil.DAOJU_MODIFY_REMIND_TITLE);
                }

                if (programData.getId() != 0 && isDaojuEnabled) {
                    doSendDaojuRemind(programData, MailContentUtil.DAOJU_NEED_REMIND_TITLE);
                }

            }
            writeChannelLog(programData.getFatherId(), Constants.LogType.DAOJU_LINK.getIndex(), entity.getOpUser(), "pid:" +
                    programData.getId() + ":daojuId:" + entity.getDaojuId() + "; flag:" + (flag == 0 ? "操作成功" : "操作失败"));

        } else if (programData.getDaojuEnable() == 1 && entity.getDaojuEnable() == 0) {
            ApiDaojuUtil.linkDaoju(programData.getQipuId(), entity.getUserName(), programData.getDaojuId(),
                    DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                    DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                    programData.getChatRoomId() + "",
                    (programData.getFreeStatus() == 1) ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                    ApiDaojuUtil.DAOJU_LINK_STATUS_OFF, null);
        }
    }

    private void writeChannelLog(long channelId, int type, String user, String descr) {
        WriteSystemLogUtil.getInstance().writeChannelLog(channelId, type, user, descr);

    }

    private void writeProgramLog(long programId, int type, String descr) {
        WriteSystemLogUtil.getInstance().writeProgramLog(programId, type, descr);
    }

    private void writeProgramLog(long programId, int type, String user, String descr) {
        WriteSystemLogUtil.getInstance().writeProgramLog(programId, type, user, descr);
    }

    public String productImg(long fatherId, String imageDatas) {
        String retValue = "";
        if (imageDatas == null || imageDatas.length() == 0) {
            retValue = "no data";
            return retValue;
        }
        ProgramService service = getProgramService();
        ProgramData programData = service.findProgramDataById(fatherId);
        if (programData == null) {
            retValue = "[productImg] data empty";
            logger.info(retValue + "[pid={}]", fatherId);
            return retValue;
        }
        retValue = ProductImgUtil.productImgProgram(fatherId, JSONArray.parseArray(imageDatas));
        return retValue;

    }

    @Override
    public boolean hasPrograms(long fatherId) {
        ProgramService service = getProgramService();
        return service.hasPrograms(fatherId);
    }

    @Override
    public String searchProgram(String name, String startDate, String endDate, String porgramQipuId, String channelQipuId, String channelName) throws TException {
        ProgramService service = getProgramService();
        return service.searchProgram(name, startDate, endDate, porgramQipuId, channelQipuId, channelName);
    }

    @Override
    public String searchFilterProgram(Map<String, String> params) throws TException {
        ProgramService service = getProgramService();
        return service.searchFilterProgram(params);
    }

    @Override
    public boolean deleteProgram(long id, String userName) throws TException {
        List<Long> idList = new ArrayList<Long>();
        idList.add(id);
        ProgramService service = getProgramService();
        ChannelService channelService = getChannelService();
        try {
            ProgramData programData = service.findProgramDataById(id);

            if (StringUtils.isNotBlank(programData.getDaojuId())) {
                // 渠道明星设置为无效
                ApiDaojuUtil.linkDaoju(programData.getQipuId(), StringUtil.unicode2String(userName), programData.getDaojuId(),
                        DateTimeUtil.transLongFormat(programData.getAddTime().getTime()),
                        DateTimeUtil.transLongFormat(DateTimeUtil.increaseDate(programData.getStopPlayTime().getTime(), 3)),
                        programData.getChatRoomId() + "",
                        (programData.getFreeStatus() == 1) ? ApiDaojuUtil.DAOJU_LIVE_TYPE_FREE : ApiDaojuUtil.DAOJU_LIVE_TYPE_PAID,
                        ApiDaojuUtil.DAOJU_LINK_STATUS_OFF, null);
            }
            ChannelBase channelBase = channelService.getChannelBase(programData.getFatherId());
            checkProgramModification(programData.getFatherId(), id, channelBase.getLiveType());

            //删除 体育赛程关联
            if (programData.getMatchSummary() != null) {
                JSONObject jsonObject = JSONObject.parseObject(programData.getMatchSummary());
                boolean result = ApiLegoUtil.updateSportRelation(ApiLegoUtil.SPORT_REMOVE_RELATION, jsonObject.getLongValue("id"), programData.getQipuId(), programData.getPname());
                if (result) {
                    programData.setMatchSummary(null);
                }
            }
            programData.setDeleteFlag(1);
            service.editProgramData(programData);
            // PPC常规直播数热门据投递
            //vv投递
            if (channelBase.getLiveType() == ChannelBase.LIVE_TYPE_LS) {
                getProgramAsyncService().addVVNotify(programData);
                ApiPpcUtil.postPpcHotSync(programData.getQipuId(), programData.getChatRoomId(), programData.getStartPlayTime().getTime(),
                        programData.getStopPlayTime().getTime(), programData.getRecommendRate(), programData.getHot(), programData.getPname(),
                        programData.getTest(), 1);
                if (programData.getSnapShotType() == 1) {
                    getSnapAsyncService().interruptTask(id);
                }
                getProgramAsyncService().addTicketSysCancelNotify(programData);
            }
            service.doSyncById(id);
            //
            channelBase.setEpisodeUpdateTime(new Timestamp(System.currentTimeMillis()));
            channelBase.setIsSync(1);
            channelService.saveBase(channelBase);
            return true;
        } catch (Exception e) {
            logger.error("[editProgram][channelBase.setEpisodeUpdateTime]", e);
        }
        return false;
    }

    @Override
    public TProgram getById(long id) throws TException {
        ProgramService service = getProgramService();
        return service.findTProgramById(id);
    }

    @Override
    public TProgramPage findProgramPage(TPage page, TFilter filter) throws TException {
        ProgramService service = getProgramService();
        TProgramPage programPage = service.findTProgramChannelPage(page, filter);
        return programPage;
    }

    @Override
    public TProgramPage findProgramLibrary(TPage page, TFilter filter) throws TException {
        ProgramService service = getProgramService();
        TProgramPage programPage = service.findLibraryPage(page, filter);
        return programPage;
    }

    @Override
    public boolean isInRange(int fatherId, String startTime, String endTime, long excludeId) {
        ProgramService service = getProgramService();
        return service.checkInRange(fatherId, startTime, endTime, excludeId);
    }

    @Override
    public String setCharge(long qipuId, String bossStatus, boolean isMemberOnly, boolean isMemberFree) {
//        if (qipuId < 1) {
//            return "错误的奇谱Id";
//        }
//        ProgramService service = getProgramService();
//        ProgramData programData = service.findProgramDataByQipuId(qipuId);
//        if (!ProgramData.PAIED_NOT_AVAILABLE.equals(programData.getBossStatus())) {
//            return "当前节目不是划价状态";
//        }
//        programData.setBossStatus(bossStatus);
//        programData.setMemberOnly(isMemberOnly ? 1 : 0);
//        programData.setMemberFree(isMemberFree ? 1 : 0);
//        service.editProgramData(programData);
//        //设置频道付费状态()
//
//        return "success";
        return "旧版过时数据";
    }

    private void doChargeChannel(ProgramData programData) {
        doChargeChannel(programData, false);
    }

    private void doChargeChannel(ProgramData programData, boolean vvNotify) {
        logger.info("[doChargeChannel][start]", programData.getFatherId());
        try {
            ChannelService channelService = getChannelService();
            ChannelBoss channelBoss = channelService.getChannelBoss(programData.getFatherId());
            if ((ProgramData.PAIED_NOT_AVAILABLE.equals(programData.getBossStatus()) && ProgramData.FREE.equals(channelBoss.getStatus()))
                    || ProgramData.PAIED_AVAILABLE.equals(programData.getBossStatus())) {
                channelBoss.setStatus(programData.getBossStatus());
                channelBoss.setIsMemberOnly(programData.getMemberOnly());
                channelBoss.setIsMemeberFree(programData.getMemberFree());
                if (programData.getPaidEndTime() != null) {
                    channelBoss.setPaidEndTime(new Timestamp(programData.getPaidEndTime().getTime()));
                }
                if (programData.getPaidStartTime() != null) {
                    channelBoss.setPaidStartTime(new Timestamp(programData.getPaidStartTime().getTime()));
                }
                channelService.saveBoss(channelBoss);
                channelService.updateChannelSync(programData.getFatherId(), 1);
            }
        } catch (Exception e) {
            logger.error("[doChargeChannel][error]", e);
        }
    }

    public String checkEpisodeBase(TProgram entity) {
        List<TProgramBase> list = entity.getRelationList();
        int countStartNum = 0;
        int countEndNum = 0;
        int countBindNum = 0;
        if (list != null) {
            for (TProgramBase temp : list) {
                if (temp.getType() == 5) {
                    countStartNum++;
                    if (countStartNum > MAX_LIMIT) {
                        return MAX_EPISODE_START_SUMMAY_MSG;
                    }
                } else if (temp.getType() == 6) {
                    countEndNum++;
                    if (countEndNum > MAX_LIMIT) {
                        return MAX_EPISODE_END_SUMMAY_MSG;
                    }
                } else if (temp.getType() == 7) {
                    countBindNum++;
                    if (countBindNum > 1) {
                        return MAX_EPISODE_SUMMAY_MSG;
                    }
                    ProgramService service = getProgramService();
                    boolean hasExist = service.checkExistBindEpisode(entity.getId(), temp.getKey());
                    if (hasExist) {
                        return BIND_EPISODE_MSG;
                    }
                }
            }
        }
        return "success";
    }


    @Override
    public TProgramBasePage findProgramBasePage(TPage page, TFilter filter) throws TException {
        return null;
    }

    @Override
    public String searchCurrentAndNextProgram(long fatherId) throws TException {
        Map<String, String> _rpcLog = new HashMap<>();
        String _rpcResponse = null;
        try {
            _rpcLog.put("typeId", "2");
            _rpcLog.put("name", "_RPC.searchCurrentAndNextProgram");
            _rpcLog.put("serverIp", InetAddress.getLocalHost().getHostAddress());
            _rpcLog.put("reqTime", String.valueOf(System.currentTimeMillis()));
            _rpcLog.put("appkey", "");
            _rpcLog.put("params", "fatherId=" + fatherId);

            ProgramService programService = null;
            try {
                programService = getProgramService();
            } catch (NullPointerException e) {
                logger.error("ApplicationContextUtil getBean Error", e);
            }
            List<Map> list = new ArrayList<>();
            if (programService != null) {
                List<ProgramData> currentNextList = programService.getCurrentAndNextProgram(fatherId, 15);
                if (!currentNextList.isEmpty()) {
                    for (ProgramData programData : currentNextList) {
                        Map<String, Object> programMap = Maps.newHashMap();
                        programMap.put("order", programData.getOrderBy());
                        programToMap(programMap, programData, fatherId);
                        if (ProgramData.TYPE_LIVE.equals(programData.getLive()) && !programMap.containsKey("playUrl")) {
                            continue;
                        }
                        list.add(programMap);
                    }
                }
            }
            if (list.isEmpty()) {
                logger.warn("未查到节目！fartherId:{}", fatherId);
                Map<String, Object> programMap = Maps.newHashMap();
                programMap.put("order", new Integer(1));
                list.add(programMap);
            }
            logger.info("query currentNextList:{}", list);
            JsonBinder jsonBinder = JsonBinder.buildNormalBinder();
            _rpcResponse = jsonBinder.toJson(list);
            return _rpcResponse;
        } catch (Exception e) {
            logger.error("[ProgramWebServiceImpl][searchCurrentAndNextProgram][Exception={}]", e);
            return null;
        } finally {
            _rpcLog.put("resTime", String.valueOf(System.currentTimeMillis()));
            _rpcLog.put("response", _rpcResponse);
            //   insertLog(_rpcLog);
        }
    }

    private LiveChannelStream getBestStream(List<LiveChannelStream> list) {
        Map<String, LiveChannelStream> map = Maps.newHashMap();
        for (LiveChannelStream single : list) {
            map.put(single.getStreamType(), single);
        }
        if (map.containsKey("RESOLUTION_1080P")) {
            return map.get("RESOLUTION_1080P");
        } else if (map.containsKey("RESOLUTION_720P")) {
            return map.get("RESOLUTION_720P");
        } else if (map.containsKey("SUPER_CLEAR")) {
            return map.get("SUPER_CLEAR");
        } else if (map.containsKey("HIGH_DEFINITION")) {
            return map.get("HIGH_DEFINITION");
        } else if (map.containsKey("SMOOTH")) {
            return map.get("SMOOTH");
        } else if (map.containsKey("TOP_SPEED")) {
            return map.get("TOP_SPEED");
        }
        return null;
    }

    private Map programToMap(Map<String, Object> currentMap, ProgramData currentProgram, Long fatherId) {
        currentMap.put("startDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentProgram.getStartPlayTime()));
        currentMap.put("endDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentProgram.getStopPlayTime()));
        currentMap.put("isLive", currentProgram.getLive());
        currentMap.put("originalId", currentProgram.getId());
        if (ProgramData.TYPE_DEMAND.equals(currentProgram.getLive())) {  //点播
            currentMap.put("episodeQipuId", currentProgram.getCarouselEpisode());
        } else if (ProgramData.TYPE_LIVE.equals(currentProgram.getLive())) {//直播
            Long liveQipuId = currentProgram.getCarouselEpisode();
            ProgramService programService = getProgramService();
            ProgramData liveProgram = programService.findProgramDataByQipuId(liveQipuId);
            LiveChannelStreamService liveChannelStreamService = (LiveChannelStreamService) ApplicationContextUtil.getBean(LiveChannelStreamService.class);
            List<LiveChannelStream> streamList = liveChannelStreamService.getByFatherId(new Long(liveProgram.getFatherId() + ""));
            if (!streamList.isEmpty()) {
                LiveChannelStream theBest = getBestStream(streamList);
                String privateIp = theBest.getStreamIp();
                String streamName = theBest.getStreamName();
                logger.info("内网ip:{}", privateIp);
                RtmpService rtmpService = (RtmpService) ApplicationContextUtil.getBean(RtmpService.class);

                String publicIp = theBest.getStreamIp();
                RtmpServer rs = rtmpService.getByPublicIp(publicIp);
                privateIp = null;
                if (rs != null) {
                    privateIp = rs.getPrivateIp();
                }
                String finalIp = StringUtils.isNotBlank(privateIp) ? privateIp : publicIp;

                currentMap.put("playUrl", "rtmp://" + finalIp + "/live/" + streamName);
            } else {
                logger.warn("当前直播节目无stream数据.fartherId:{}", liveProgram.getFatherId());
            }
        }
        return currentMap;
    }

    @Override
    public String daySortProgram(long fatherId, String sortDate) throws TException {
        String retValue = "success";
        ProgramService service = getProgramService();
        long sortBeginTime = DateTimeUtil.parseLongFormat(sortDate);

        String shortDate = DateTimeUtil.transShortFormat(sortBeginTime);
        List<ProgramData> programDataList = service.getByDay(shortDate, (int) fatherId);
        if (programDataList.size() == 0) {
            return retValue;
        }

        long checkTime = System.currentTimeMillis() + PROGRAM_EDIT_RESERVE_TIME;

        String checkDate = DateTimeUtil.transShortFormat(checkTime);
        if (checkDate.compareTo(shortDate) > 0) {
            return "只能重排" + checkDate + "之后的数据!";
        }
        List<ProgramNodeElement> nodeElementList = ProgramDaySortUtil.transToProgramNodeElementList(programDataList);
        long dayStartTime = DateTimeUtil.parseLongFormat(shortDate + " 00:00:00");
        long dayEndTime = DateTimeUtil.parseLongFormat(shortDate + " 23:59:59");
        long yesterdayEndTime = service.findYesDayEndTime(fatherId, dayStartTime);
        List<ProgramNode> nodeList = ProgramDaySortUtil.transToProgramNodeList(nodeElementList, dayStartTime, dayEndTime, checkTime, yesterdayEndTime);
        if (nodeList.size() == 1) {
            logger.info("[daySortProgram] no need to sort");
            return retValue;
        }

        ProgramDaySortUtil.dealNodelList(nodeList, nodeElementList, dayEndTime);
        List<TProgramTime> moveList = ProgramDaySortUtil.calculateTProgramTime(nodeList, dayEndTime);
        if (moveList.size() == 0) {
            return retValue;
        }
        checkTomorrowProgramList(service, fatherId, moveList);
        Map<Long, TProgramTime> dataMap = transToMap(moveList);
        boolean sqlResult = service.updateProgramTimeList(dataMap);
        if (!sqlResult) {
            retValue = "重排节目失败";
        } else {
            TProgramTime checkSendTarget = moveList.get(0);
            checkProgramModification(fatherId, checkSendTarget.getId(), ChannelBase.LIVE_TYPE_LB);
        }

        return retValue;
    }

    private void checkTomorrowProgramList(ProgramService service, long fatherId, List<TProgramTime> moveList) {
        logger.info("[checkTomorrowProgramList start][fatherId={}]", fatherId);
        long endTime = -1;
        long tempEndTime = -1;
        for (TProgramTime tProgramTime : moveList) {
            if (ProgramDaySortUtil.checkIsOverDay(Long.valueOf(tProgramTime.getStartPlayTime()), Long.valueOf(tProgramTime.getStopPlayTime()))) {
                tempEndTime = Long.valueOf(tProgramTime.getStopPlayTime());
                if (tempEndTime > endTime) {
                    endTime = tempEndTime;
                }
            }
        }
        if (endTime < 1) {
            return;
        }
        Map<String, String> params = new HashMap();
        params.put("EQI_deleteFlag", 0 + "");
        params.put("EQI_illegalStatus", 0 + "");
        params.put("EQI_fatherId", (int) fatherId + "");
        params.put("LTT_startPlayTime", DateTimeUtil.transLongFormat(endTime + 5 * DateTimeUtil.MINUTE_TIME));
        params.put("GET_startPlayTime", DateTimeUtil.transLongFormat(DateTimeUtil.getZeroTime(endTime)));
        TFilter tFilter = new TFilter();
        tFilter.setFilters(params);
        List<ProgramData> programList = service.findProgramDataList(tFilter, "startPlayTime,lastSortTime", "asc,desc");
        //
        //   int length = programList.size();
        List<Long> newAddList = new ArrayList<Long>();
        if (programList.size() > 0) {

            long checkLimitTime = endTime;
            int count = 0;
            for (ProgramData program : programList) {
                if (program.getIsLocked() == ProgramData.PROGRAM_LOCKED || (program.getLive() != null && ProgramData.TYPE_LIVE.compareTo(program.getLive()) == 0)) {
                    continue;
                }
                if (program.getStartPlayTime().getTime() > checkLimitTime) {
                    break;
                } else {
                    TProgramTime tProgramTime = new TProgramTime();
                    tProgramTime.setId(program.getId());
                    tProgramTime.setStartPlayTime((checkLimitTime + DateTimeUtil.SECOND * program.getAdvertDuration()) + "");
                    tProgramTime.setStopPlayTime((checkLimitTime + DateTimeUtil.SECOND * program.getAdvertDuration() + program.getStopPlayTime().getTime() - program.getStartPlayTime().getTime()) + "");
                    tProgramTime.setStartStreamTime(tProgramTime.getStartPlayTime());
                    tProgramTime.setStopStreamTime(tProgramTime.getStopPlayTime());
                    checkLimitTime += DateTimeUtil.SECOND;
                    moveList.add(tProgramTime);
                    newAddList.add(program.getId());
                }
            }
        }
        logger.info("[checkTomorrowProgramList end][affect ids={}]", newAddList.toString());
    }

    private Map<Long, TProgramTime> transToMap(List<TProgramTime> dataList) {
        Map<Long, TProgramTime> dataMap = new HashMap<>();
        for (TProgramTime temp : dataList) {
            dataMap.put(temp.getId(), temp);
        }
        return dataMap;
    }


    /**
     * 节目上移下移接口
     *
     * @param id           节目ID
     * @param flag         上移下移判断(1. 上移， 2. 下移)
     * @param fatherId     频道ID
     * @param operationDay 操作的日期(格式： 2015-07-13)
     * @return result (0. 正常, 1. 操作失败 2. 无法操作 3.没有上一个节目无法上移 4.没有下一个节目无法下移,5:跨天节目不能上移/下移)
     * @throws TException
     */
    @Override
    public int moveProgram(long id, int flag, long fatherId, String operationDay) throws TException {
        ProgramService service = getProgramService();
        ProgramData curProgram = null; // 当前节目
        ProgramData prevProgram = null; // 上一个节目
        ProgramData nextProgram = null; // 下一个节目

        // check whether the operation program exists
        TProgram program = service.findTProgramById(id, false);
        if (null == program) {
            return PROGRAM_MOVE_ERR;
        }

        // Get the program list
        Map<String, String> params = new HashMap();
        params.put("EQI_deleteFlag", 0 + "");
        params.put("EQI_fatherId", fatherId + "");
        params.put("GET_startPlayTime", operationDay + " 00:00:00");
        params.put("LET_startPlayTime", operationDay + " 23:59:59");
        params.put("NEQI_live", 2 + "");
        params.put("NEQI_isLocked", 1 + "");

        TFilter tFilter = new TFilter();
        tFilter.setFilters(params);
        List<ProgramData> dataResult = service.findProgramDataList(tFilter, "startPlayTime,lastSortTime", "asc,desc");

        // The program cannot be moved if no other programs.
        if (null == dataResult || dataResult.size() <= 1) {
            return PROGRAM_MOVE_ERR;
        }

        // The program cannot be moved up if the current program is at the top, neither moved down at the bottom.
        if ((dataResult.get(0).getId() == id && flag == 1)) {
            return PROGRAM_MOVE_ERR_NOUP;
        }

        if ((dataResult.get(dataResult.size() - 1).getId() == id) && flag == 2) {
            return PROGRAM_MOVE_ERR_NODOWN;
        }

        if (dataResult.size() == 2) {
            if (flag == 1) {
                prevProgram = dataResult.get(0);
                curProgram = dataResult.get(1);
            } else if (flag == 2) {
                curProgram = dataResult.get(0);
                nextProgram = dataResult.get(1);
            }
        } else if (dataResult.get(0).getId() == id) {     // 最前面一个节目下移
            nextProgram = dataResult.get(1);
            curProgram = dataResult.get(0);
        } else if (dataResult.get(dataResult.size() - 1).getId() == id) {  // 最后面一个节目上移
            prevProgram = dataResult.get(dataResult.size() - 2);
            curProgram = dataResult.get(dataResult.size() - 1);
        } else {
            for (int i = 1; i < dataResult.size() - 1; ++i) {
                prevProgram = dataResult.get(i - 1);
                curProgram = dataResult.get(i);
                nextProgram = dataResult.get(i + 1);

                if (curProgram.getId() == id) {
                    break;
                }
            }
        }

        // Update program data
        List<TProgramTime> tempList = null;
        long reserveTime = Configuration.getLong("program.edit.forbidden.reserve.time") * 60 * 1000;

        if (flag == 1) {
            if (ProgramDaySortUtil.checkIsOverDay(prevProgram) || ProgramDaySortUtil.checkIsOverDay(curProgram)) {
                return PROGRAM_MOVE_ERR_OVERDAY;
            }
            if (getAdvertStartTime(prevProgram) - System.currentTimeMillis() < reserveTime) {
                return PROGRAM_MOVE_ERR_EXPIRED;
            }
            tempList = exchangeTime(prevProgram, curProgram);
        } else if (flag == 2) {
            if (ProgramDaySortUtil.checkIsOverDay(curProgram) || ProgramDaySortUtil.checkIsOverDay(nextProgram)) {
                return PROGRAM_MOVE_ERR_OVERDAY;
            }
            if (getAdvertStartTime(curProgram) - System.currentTimeMillis() < reserveTime) {
                return PROGRAM_MOVE_ERR_EXPIRED;
            }

            tempList = exchangeTime(curProgram, nextProgram);
        }
        boolean retFlag = service.updateProgramTimeList(tempList);
        if (!retFlag) {
            return PROGRAM_MOVE_ERR;
        }

        if (flag == 1) {
            checkProgramModification(fatherId, id, ChannelBase.LIVE_TYPE_LB);
        } else if (flag == 2) {
            checkProgramModification(fatherId, nextProgram.getId(), ChannelBase.LIVE_TYPE_LB);
        }

        return PROGRAM_MOVE_SUC;
    }

    private List<TProgramTime> exchangeTime(ProgramData data1, ProgramData data2) {
        List<TProgramTime> resultList = new ArrayList<>();
        TProgramTime programTime1 = new TProgramTime();
        TProgramTime programTime2 = new TProgramTime();

        long duration1 = data1.getStopPlayTime().getTime() - data1.getStartPlayTime().getTime();
        long duration2 = data2.getStopPlayTime().getTime() - data2.getStartPlayTime().getTime();

        programTime1.setId(data1.getId());
        programTime1.setStopPlayTime(Long.toString(data2.getStopPlayTime().getTime()));
        programTime1.setStopStreamTime(programTime1.getStopPlayTime());
        programTime1.setStartPlayTime(Long.toString(data2.getStopPlayTime().getTime() - duration1));
        programTime1.setStartStreamTime(programTime1.getStartPlayTime());

        programTime2.setId(data2.getId());
        long newBeginTime = getAdvertStartTime(data1) + DateTimeUtil.SECOND * data2.getAdvertDuration();
        programTime2.setStartPlayTime(Long.toString(newBeginTime));
        programTime2.setStartStreamTime(programTime2.getStartPlayTime());
        programTime2.setStopPlayTime(Long.toString(newBeginTime + duration2));
        programTime2.setStopStreamTime(programTime2.getStopPlayTime());
        resultList.add(programTime1);
        resultList.add(programTime2);
        return resultList;
    }

    @Override
    public int toggleLockProgram(long id, long fatherId, int lockType) {
        ProgramService service = getProgramService();

        try {
            if (service.toggleLockProgram(id, lockType)) {
                return 0;
            } else {
                return -1;
            }
        } catch (Exception e) {
            logger.info("[ProgramWebServiceImpl][toggleLockProgram][Exception={}]", e);
            return -1;
        }
    }

    /**
     * 轮播台中引用的节目单发生变化
     *
     * @param programData 修改的节目信息
     */
    private void sendEmailNotify(String oldTime, String newTime, ProgramData programData, ChannelBase editChannelBase) {
        Map<String, String> params = new HashMap();

        params.put("EQI_program.is_delete", 0 + "");
        params.put("EQL_program.carousel_episode", String.valueOf(programData.getQipuId()));
        TFilter tFilter = new TFilter();
        tFilter.setFilters(params);
        TPage page = new TPage(-1, 1, 10000, "id", "desc", false);
        try {
            TProgramPage data = findProgramPage(page, tFilter);
            if (data.getResultSize() == 0) {
                return;
            }

            String title = CHANNEL_NOTIFY_TITLE;
            String content = CHANNEL_NOTIFY_CONTENT;

            title = title.replace("${channel}", editChannelBase.getName());
            title = title.replace("${program}", programData.getPname());

            content = content.replace("${channel}", editChannelBase.getName());
            content = content.replace("${program}", programData.getPname());
            content = content.replace("${pQipuId}", String.valueOf(programData.getQipuId()));
            content = content.replace("${cQipuId}", String.valueOf(editChannelBase.getQipuId()));
            content = content.replace("${oldTime}", oldTime);
            content = content.replace("${newTime}", newTime);

            logger.info("[ProgramWebServiceImpl][sendEmailNotify][title = {} ][content = {} ]", title, content);
            for (TProgram temp : data.getResult()) {
                if (temp.getQipuId() == 0) {
                    continue;
                }
                doSendErrorMail(temp.getFatherId(), title, content);
            }

        } catch (TException e) {
            logger.error("[ProgramWebServiceImpl][sendEmailNotify][exception=]", e);
        }
    }

    @Override
    public String proxyToPuYu(String barCode, String cprVideoName) {
        ProgramService service = getProgramService();
        return service.queryPuYu(barCode, cprVideoName);

    }

    private long getAdvertStartTime(ProgramData programData) {
        return programData.getStartPlayTime().getTime() - DateTimeUtil.SECOND * programData.getAdvertDuration();
    }

    @Override
    public int indexMove(long id, long aimId, String dateTime, long fatherId) {
        logger.info("[ProgramWebServiceImpl][indexMove] params [id={}][aimId={}][dateTime={}][fatherId={}]", id, aimId, dateTime, fatherId);
        ProgramService service = getProgramService();
        List<ProgramData> programList = service.getByDay(dateTime, (int) fatherId);
        ProgramData current = null;
        ProgramData aimTarget = null;
        long checkTime = System.currentTimeMillis() + PROGRAM_EDIT_RESERVE_TIME;
        for (ProgramData temp : programList) {
            if (temp.getId() == id) {
                current = temp;
            } else if (temp.getId() == aimId) {
                aimTarget = temp;
            }
        }
        if (current == null) {
            logger.info("[ProgramWebServiceImpl][indexMove][id={}])", id);
            return PROGRAM_INDEX_MOVE_ERR_NO_CURRENTTARGET;
        }
        if (aimTarget == null) {
            logger.info("[ProgramWebServiceImpl][indexMove][aimId={}])", id);
            return PROGRAM_INDEX_MOVE_ERR_NO_AIMTARGET;
        }
        if (current.getLive() != null && current.getLive().intValue() == ProgramData.TYPE_LIVE) {
            return PROGRAM_INDEX_MOVE_ERR_NO_LIVE;
        }

        if (getAdvertStartTime(current) < checkTime) {
            return PROGRAM_INDEX_MOVE_ERR_OVERTIME_CURRENT;
        }
        if (getAdvertStartTime(aimTarget) < checkTime) {
            return PROGRAM_INDEX_MOVE_ERR_OVERTIME_AIM;
        }
        try {

            long minDateTime = DateTimeUtil.parseShortFormat(dateTime);
            if (minDateTime < checkTime) {
                minDateTime = checkTime;
            }
            long newEndTime = getAdvertStartTime(aimTarget);
            if (minDateTime > newEndTime) {
                return PROGRAM_INDEX_MOVE_ERR_START_END_TIME;
            }
            long newStartTime = newEndTime - current.getDuration() * 1000L;
            if (newStartTime < minDateTime) {
                newStartTime = minDateTime;
            }

            int aimIndex = programList.indexOf(aimTarget);
            if (aimIndex > 0) {
                ProgramData preProgramData = programList.get(aimIndex - 1);
                if (preProgramData.getId() == current.getId()) {
                    if (aimIndex > 1) {
                        preProgramData = programList.get(aimIndex - 2);
                        newStartTime = judgeNewStartTime(preProgramData, newStartTime, newEndTime);
                    }
                } else {
                    newStartTime = judgeNewStartTime(preProgramData, newStartTime, newEndTime);
                }
            }
            current.setStartPlayTime(new Timestamp(newStartTime + DateTimeUtil.SECOND * current.getAdvertDuration()));
            current.setStopPlayTime(new Timestamp(newEndTime));
            current.setStreamStartTime(new Timestamp(newStartTime + DateTimeUtil.SECOND * current.getAdvertDuration()));
            current.setStreamEndTime(new Timestamp(newEndTime));
            ProgramData.calPlayStatus(current);
            long lastSortTime = System.currentTimeMillis();
            current.setLastSortTime(lastSortTime);
            List<ProgramData> updateList = new ArrayList<ProgramData>();
            updateList.add(current);
            ProgramData sameStartTimeData = null;
            for (int i = aimIndex - 1; i > -1; i--) {
                sameStartTimeData = programList.get(i);
                if (sameStartTimeData.getStartPlayTime().getTime() == current.getStartPlayTime().getTime()) {
                    sameStartTimeData.setLastSortTime(lastSortTime + (aimIndex - i));
                    updateList.add(sameStartTimeData);
                } else {
                    break;
                }
            }
            service.updateFlagProgramDataList(updateList);
            checkProgramModification(fatherId, current.getId(), ChannelBase.LIVE_TYPE_LB);
            return PROGRAM_INDEX_MOVE_SUC;
        } catch (Exception e) {
            logger.info("[ProgramWebServiceImpl][indexMove] params error happend [id={}][aimId={}][dateTime={}][fatherId={}]", id, aimId, dateTime, fatherId);
            logger.error("[ProgramWebServiceImpl][indexMove] [error={}]", e);
            return PROGRAM_INDEX_MOVE_ERR;
        }

    }

    private long judgeNewStartTime(ProgramData preProgramData, long newStartTime, long newEndTime) {
        if (getAdvertStartTime(preProgramData) == newEndTime || preProgramData.getStopPlayTime().getTime() >= newEndTime) {
            newStartTime = newEndTime;
        } else if (preProgramData.getStopPlayTime().getTime() < newEndTime) {
            if (newStartTime < preProgramData.getStopPlayTime().getTime()) {
                newStartTime = preProgramData.getStopPlayTime().getTime();
            }
        }
        return newStartTime;
    }

    @Override
    public int batchDel(List<Long> idList, String dateTime, long channelId) {
        logger.info("[ProgramWebServiceImpl][batchDel][channelId={}][idList={}][dateTime={}]", channelId, idList.toString(), dateTime);
        ProgramService service = getProgramService();
        List<ProgramData> programList = service.getByDay(dateTime, (int) channelId);
        List<ProgramData> programDelList = new ArrayList<ProgramData>();
        ChannelService channelService = getChannelService();
        ChannelBase channelBase = channelService.getChannelBase(channelId);
        long currentTime = System.currentTimeMillis();
        boolean isLB = channelBase.getLiveType() == ChannelBase.LIVE_TYPE_LB;
        for (ProgramData programData : programList) {
            if (idList.remove(programData.getId())) {
                if (!isLB || (currentTime + PROGRAM_EDIT_RESERVE_TIME < programData.getStartPlayTime().getTime())) {
                    programDelList.add(programData);
                }
            }

        }

        if (null != programList.get(0)) {
            checkProgramModification(channelBase.getId(), programList.get(0).getId(), channelBase.getLiveType());
        }
        try {
            logger.info("[ProgramWebServiceImpl][batchDel] [fail to excute={}]", idList.toString());
            logger.info("[ProgramWebServiceImpl][batchDel] [excuteSize={}]", programDelList.size());
            if (programDelList.size() > 0) {
                service.deleteFlagProgramDataList(programDelList);
                channelBase.setEpisodeUpdateTime(new Timestamp(System.currentTimeMillis()));
                channelBase.setIsSync(1);
                channelService.saveBase(channelBase);
            }
            return 1;
        } catch (Exception e) {
            logger.error("[ProgramWebServiceImpl][batchDel][exception={}]", e);
            return -1;
        }
    }


    @Override
    public int saveStreamError(int errorCode, long channelId, long programId, String streamName, int errorAll) {
        logger.info("[ProgramWebServiceImpl][saveStreamError][errorCode={}][channelId={}][programId={}][streamName={}][errorAll={}]",
                errorCode, channelId, programId, streamName, errorAll);
        int result = 0;
        boolean needUpdateData = true;
        List<String> _streamTypeList = new ArrayList<>();

        try {
            ProgramService programService = getProgramService();
            LiveChannelStreamService liveChannelStreamService = (LiveChannelStreamService) ApplicationContextUtil.getBean(LiveChannelStreamService.class);
            ChannelService channelService = getChannelService();

            if (1 != errorAll) {

                LiveChannelStream liveChannelStream = liveChannelStreamService.get(channelId, streamName);

                if (null == liveChannelStream || null == liveChannelStream.getStreamType()) {
                    logger.info("[ProgramWebServiceImpl][saveStreamError][channelId={}][streamName={}][cannot find the livechannelstream]",
                            channelId, streamName);
                    needUpdateData = false;
                } else {

                    _streamTypeList.add(liveChannelStream.getStreamType());
                }
            } else {
                List<LiveChannelStream> liveChannelStreamList = liveChannelStreamService.getByFatherId(channelId);

                if (null == liveChannelStreamList || 0 == liveChannelStreamList.size()) {
                    needUpdateData = false;
                } else {

                    for (LiveChannelStream liveChannelStream : liveChannelStreamList) {
                        if (LiveChannelStream.STATUS_ACTIVED == liveChannelStream.getStatus()) {
                            _streamTypeList.add(liveChannelStream.getStreamType());
                        }
                    }
                }
            }


            // update error info
            if (needUpdateData) {
                if (!programService.addStreamError(errorCode, channelId, programId, _streamTypeList)) {
                    result = -1;
                    logger.info("[ProgramWebServiceImpl][saveStreamError][addStreamError][failed]");
                }
            }

            ChannelBase currentChannel = channelService.getChannelBase(channelId);
            ProgramData programData = programService.findProgramDataById(programId);

            // send mail to editors
            String title = STREAM_ERROR_TITLE;
            String content = STREAM_ERROR_CONTENT;

            title = title.replace("${channelName}", currentChannel.getName());

            content = content.replace("${channelName}", currentChannel.getName());
            content = content.replace("${programName}", programData.getPname());
            content = content.replace("${pQipuId}", String.valueOf(programData.getQipuId()));
            content = content.replace("${cQipuId}", String.valueOf(currentChannel.getQipuId()));
            content = content.replace("${startTime}", DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()));
            content = content.replace("${stopTime}", DateTimeUtil.transLongFormat(programData.getStopPlayTime().getTime()));

            logger.info("[ProgramWebServiceImpl][saveStreamError][sendMail][title = {} ][content = {} ]", title, content);

            if (!sendMailForChannel(channelId, title, content)) {
                result = -1;
                logger.info("[ProgramWebServiceImpl][saveStreamError][sendMail][failed]");
            }
        } catch (Exception e) {
            logger.error("[ProgramWebServiceImpl][saveStreamError][error][exception={}", e);
            result = -1;
        }

        return result;
    }

    private boolean sendMailForChannel(long channelId, String title, String content) {
        try {
            // 跟据要发送的人员来修改
            String[] tos = getNoticeMailService().getTos(channelId, 0, MailConstant.TOS_TYPE_FROM_STREAM_LOG + MailConstant.TOS_TYPE_STREAM_ERROR_GROUP);
            // 开发人员邮件组
            if (tos.length == 0) {
                return true;
            }
            SendMailUtils.send(title, tos, content);
            logger.info("[ProgramWebServiceImpl][sendMailForChannel][tos = {}]", tos);

            return true;
        } catch (Exception e) {
            logger.info("[ProgramWebServiceImpl][sendMailForChannel][failed]");
            return false;
        }
    }

    private void checkProgramModification(long channelId, long programId, int liveType) {
        ChannelNotifyUtil.checkProgramModification(channelId, programId, liveType);
    }

    private void doSendErrorMail(long channelId, String title, String content) {
        try {
            String[] tos = getNoticeMailService().getTos(channelId, 0, MailConstant.TOS_TYPE_FROM_CAROUSEL_LOG);
            if (tos.length == 0) {
                return;
            }
            SendMailUtils.send(title, tos, content);
            logger.info("[ProgramWebServiceImpl][doSendEMail][title={}][tos = {}]", title, tos);
        } catch (Exception e) {
            logger.error("[doSendEMail][exception={}]", e);
        }
    }

    public long getYesterdayEndTime(long channelId, long newStartTime) {
        try {
            ProgramService service = getProgramService();
            return service.findYesDayEndTime(channelId, newStartTime);
        } catch (Exception e) {
            logger.error("[getYesterdayEndTime][exception={}]", e);
            return -1;
        }
    }

    @Override
    public List<TLivingInfo> getTLivingInfo() throws TException {
        List<TLivingInfo> liveInfo = new ArrayList<>();
        try {
            ProgramService service = getProgramService();
            return service.getTLivingInfo();
        } catch (Exception e) {
            logger.error("[getTLivingInfo][exception={}]", e);
            return liveInfo;
        }
    }

    private void insertLog(Map<String, String> logData) {
        InterfaceLogService service = (InterfaceLogService) ApplicationContextUtil.getBean(InterfaceLogService.class);
        InterfaceLog interfaceLog = JSONObject.parseObject(JSON.toJSONString(logData), InterfaceLog.class);
        interfaceLog.setPlatform(Byte.valueOf("1"));
        Long usageTime = (interfaceLog.getResTime().getTime() - interfaceLog.getReqTime().getTime()) / 1000;
        interfaceLog.setUsageTime(usageTime.intValue());
        if (interfaceLog.getAppkey() == null) {
            interfaceLog.setAppkey("");
        }
        service.save(interfaceLog);
    }

    @Override
    public String getMaxDurationProgram(long fatherId) {
        try {
            ProgramService service = getProgramService();
            return service.getMaxDurationProgram(fatherId);
        } catch (Exception e) {
            logger.error("[ProgramWebServiceImpl][getMinDurationProgram][exception={}]", e);
            return null;
        }
    }

    private void doSendDaojuRemind(ProgramData program, String mailTitle) {
        try {
            String[] tos = getNoticeMailService().getTos(0, 0, MailConstant.TOS_TYPE_DAOJU_MAIL_GROUP);
            Map<String, String> map = new HashMap<>();
            map.put(MailConstant.P_NAME, program.getPname());
            map.put(MailConstant.P_QIPU_ID, "" + program.getQipuId());
            map.put(MailConstant.P_START_TIME, DateTimeUtil.transLongFormat(program.getStartPlayTime().getTime()));
            map.put(MailConstant.P_STOP_TIME, DateTimeUtil.transLongFormat(program.getStopPlayTime().getTime()));
            String title = String.format(mailTitle, program.getPname());
            String content = MailContentUtil.getContent(MailContentUtil.ContentType.DAOJU_REMIND, map);
            SendMailUtils.send(title, tos, content);
            logger.info("[ProgramWebServiceImpl][doSendDaojuRemind][title={}][tos = {}]", title, tos);
        } catch (Exception e) {
            logger.error("[doSendDaojuRemind][exception={}]", e);
        }
    }

    private void doSendCreateLiveNotify(ProgramData programData, ChannelBase channelBase, String episodeGrade, String opUser) {
        logger.info("[doSendCreateLiveNotify][pqid={}][opuser={}]", programData.getQipuId(), opUser);
        Map<String, String> map = new HashMap<String, String>();
        map.put(MailConstant.P_NAME, programData.getPname());
        map.put(MailConstant.C_QIPU_ID, "" + channelBase.getQipuId());
        map.put(MailConstant.P_QIPU_ID, "" + programData.getQipuId());
        map.put(MailConstant.P_START_TIME, DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()));
        map.put(MailConstant.P_STOP_TIME, DateTimeUtil.transLongFormat(programData.getStopPlayTime().getTime()));
        map.put(MailConstant.P_PAGE_URL, programData.getPageUrl());
        map.put(MailConstant.OP_USER, opUser);
        map.put(MailConstant.P_ADD_TIME, DateTimeUtil.transLongFormat(programData.getAddTime().getTime()));
        map.put(MailConstant.P_EPISODE_GRADE, episodeGrade);
        map.put(MailConstant.ASSIGN_TITLE, String.format(MailContentUtil.getTitleTemplate(MailContentUtil.ContentType.PROGRAM_CREATE_LIVE_NOTIFY), programData.getPname()));
        NotifyMailService notifyMailService = (NotifyMailService) ApplicationContextUtil.getBean(NotifyMailService.class);
        notifyMailService.addMailAsyncTask(MailConstant.TOS_TYPE_LS_ADD_NOTIFY + MailConstant.TOS_TYPE_EPG_TEAM, MailContentUtil.ContentType.PROGRAM_CREATE_LIVE_NOTIFY.getTypeIndex(), map);
    }


    @Override
    public int programForceCheck(long programId) throws TException {
        try {
            ProgramService service = getProgramService();
            return service.updateToForceCheck(programId);
        } catch (Exception e) {
            logger.error("[ProgramWebServiceImpl][programForceCheck]", e);
            return -1;
        }
    }

    private boolean checkNeedPpcHotSync(ProgramData oldOne, TProgram newOne) {
        if (oldOne.getChatRoomId() != newOne.getChatRoomId() ||
                oldOne.getStartPlayTime().getTime() != DateTimeUtil.parseLongFormat(newOne.getStartPlayTime()) ||
                oldOne.getStopPlayTime().getTime() != DateTimeUtil.parseLongFormat(newOne.getEndPlayTime()) ||
                oldOne.getRecommendRate() != newOne.getRecommendRate() ||
                oldOne.getHot() != newOne.getHot() ||
                oldOne.getTest() != newOne.getTest()) {
            logger.info("[ProgramWebServiceImpl][checkNeedPpcHotSync][qipuId={}][true]", oldOne.getQipuId());
            return true;
        }
        logger.info("[ProgramWebServiceImpl][checkNeedPpcHotSync][qipuId={}][false]", oldOne.getQipuId());
        return false;
    }

    @Override
    public TProgramLogPage getProgramLogList(TPage page, TFilter filter) throws TException {
        ProgramService service = getProgramService();
        TProgramLogPage tProgramLogPage = service.getProgramLogList(page, filter);
        return tProgramLogPage;
    }

    @Override
    public boolean saveProgramLog(TProgramLog entity) throws TException {
        if (entity == null) {
            return false;
        }
        ProgramService service = getProgramService();
        ProgramLog programLog = new ProgramLog();
        programLog.setDescription(entity.getDescr());
        programLog.setProgramId(entity.getProgramId());
        programLog.setUser(entity.getUser());
        programLog.setType(entity.getType());
        service.saveProgramLog(programLog);
        return programLog.getId() > 0;
    }

    @Override
    public String snapshot(long taskId, String snapshot, String errcode, String errmsg) throws TException {
        ProgramService service = getProgramService();
        String decodeSnapShot = null;
        if (Constants.CODE_SUC.equals(errcode)) {
            decodeSnapShot = new String(Base64.decode(snapshot));
        }
        String saveResult = service.saveSnapshot(taskId, decodeSnapShot, errcode, errmsg);
        StringBuffer sb = new StringBuffer();
        sb.append("url=" + decodeSnapShot + ";")
                .append("errcode=" + errcode + ";")
                .append("errmsg=" + errmsg + ";")
                .append("saveResult=" + saveResult + ";");
        writeProgramLog(taskId,
                Constants.LogType.STREAM_SNAPSHOT_WRITE.getIndex(), sb.toString());
        JSONObject result = null;
        if (decodeSnapShot != null) {
            String url = Configuration.getString("product.meizhi.img.url");
            Map<String, String> params = new HashMap<String, String>();
            params.put("entityId", taskId + "");
            params.put("entityType", "37");
            params.put("useType", "606");
            params.put("businessType", "6");
            params.put("fromType", "1");
            //  params.put("url", snapshot);
            params.put("url", decodeSnapShot);
            params.put("area", "sh");
            params.put("extend", Constants.EXTEND_NEW_EPG_PROGRAM_SNAPSHOT);
            result = ApiHttpRequestUtil.getMethod(url, params);
            sb = new StringBuffer();
            sb.append("url=" + decodeSnapShot + ";")
                    .append("errcode=" + errcode + ";")
                    .append("errmsg=" + errmsg + ";")
                    .append("result=" + result + ";");
            writeProgramLog(taskId,
                    Constants.LogType.MEIZI_SNAPSHOT_PUSH.getIndex(), sb.toString());
            logger.info("[snapshot][result={}]", result == null ? null : result.toString());
        }

        return saveResult;

    }

    @Override
    public int modifyAdvert(long id, int enable) throws TException {
        ProgramService service = getProgramService();
        ProgramData programData = service.findProgramDataById(id);
        if (programData == null) {
            return -2;
        }
        if (enable == programData.getAdvertEnable()) {
            return 0;
        } else {
            programData.setAdvertEnable(enable);
            service.updateDBAdvert(programData);
            service.editProgramData(programData);
            service.doSyncById(id);
        }
        return 0;
    }


    public int moveAdvert(long id, int moveDirection) throws TException {
        return 0;
    }

    @Override
    public TResponse getRtmpStream(TFilter filter) throws TException {
        TResponse tResponse = new TResponse();
        tResponse.setCode(Constants.CODE_SUC);
        ProgramService service = getProgramService();
        String sQipuId = filter.getFilters().get("qipuId");
        ProgramData programData = service.findProgramDataByQipuId(Long.valueOf(sQipuId));
        if (programData == null || programData.getDeleteFlag() == 1) {
            tResponse.setCode(Constants.CODE_FAIL);
            tResponse.setMsg("节目不存在");
            return tResponse;
        }
        LiveChannelStreamServiceImpl streamService = (LiveChannelStreamServiceImpl) ApplicationContextUtil.getBean(LiveChannelStreamServiceImpl.class);
        JSONObject jsonObject = streamService.getUrlObj(programData.getFatherId());
        tResponse.setJsonData(jsonObject.toJSONString());
        return tResponse;
    }

    @Override
    public TResponse unbindSport(long programQipuId, long matchId) throws TException {
        TResponse tResponse = new TResponse();
        tResponse.setCode(Constants.CODE_SUC);
        JSONObject jsonObject = new JSONObject();
        ProgramService service = getProgramService();
        ProgramData programData = service.findProgramDataByQipuId(Long.valueOf(programQipuId));
        if (programData != null) {
            if (programData.getMatchSummary() != null) {
                boolean result = ApiLegoUtil.updateSportRelation(ApiLegoUtil.SPORT_REMOVE_RELATION, matchId, programQipuId, programData.getPname());
                jsonObject.put("apiRetValue", result);
                if (result) {
                    programData.setMatchSummary(null);
                    service.editProgramData(programData);
                    service.doSyncById(programData.getId());
                } else {
                    tResponse.setCode(Constants.CODE_FAIL);
                }
            }
            jsonObject.put("entityId", programData.getId());
            tResponse.setJsonData(jsonObject.toJSONString());
        } else {
            jsonObject.put("entityId", -1);
            tResponse.setJsonData(jsonObject.toJSONString());
            tResponse.setCode(Constants.CODE_ERROR);
        }
        return tResponse;
    }


    @Override
    public TResponse saveOAInfo(TInfoOA entity) throws TException {
        TResponse tResponse = new TResponse();
        tResponse.setCode(Constants.CODE_SUC);
        JSONObject jsonObject = new JSONObject();
        IqiyiOAData saveData = new IqiyiOAData();
        saveData.setDocNo(entity.getDocNo());
        saveData.setChiefEditorApprovalStatus(entity.getChiefEditorApprovalStatus());
        saveData.setDocStatus(entity.getDocStatus());
        saveData.setLiveLevel(entity.getLiveLevel());
        saveData.setLiveLevelABC(entity.getLiveLevelABC());
        saveData.setAddTime(new Timestamp(System.currentTimeMillis()));
        try {
            ProgramService service = getProgramService();
            long entityId = service.saveOAData(saveData);
            jsonObject.put("entityId", entityId);
            tResponse.setJsonData(jsonObject.toJSONString());
            if ("checked".equals(saveData.getChiefEditorApprovalStatus())) {
                int value = transToEpisodeGrade(saveData.getLiveLevel(), saveData.getLiveLevelABC());
                if (value > 0) {
                    service.updateDocEditStatusByDocNo(saveData, value);
                    getTicketService().updateOaByOaDoc(saveData.getDocNo(), saveData.getChiefEditorApprovalStatus());
                } else {
                    logger.warn("[docNo={}][entityId={}] ", saveData.getDocNo(), entityId);
                }
            } else {
                service.updateDocEditStatusByDocNo(saveData);
            }
        } catch (Exception e) {
            jsonObject.put("entityId", -1);
            tResponse.setJsonData(jsonObject.toJSONString());
            tResponse.setCode(Constants.CODE_FAIL);
            logger.error("[saveOAInfo]", e);
        }
        return tResponse;
    }

    private static int transToEpisodeGrade(String live, String liveABC) {
        if (StringUtils.isBlank(live) || StringUtils.isBlank(liveABC)) {
            return 0;
        }
        int baseValue = 100;
        try {
            baseValue += Integer.valueOf(live) + 10 * (Integer.valueOf(liveABC) - 1);
        } catch (Exception e) {
            logger.error("[transToEpisodeGrade]", e);
            return 0;
        }
        return baseValue;
    }
}
